<template>
  <div
    class="icon-selector"
    role="combobox"
    :aria-expanded="state.isSearching"
    :aria-haspopup="true"
    :aria-label="placeholder"
  >
    <!-- 自定义输入框 -->
    <div
      class="custom-input-wrapper"
      :class="[`input-${size}`, { 'input-disabled': disabled }]"
    >
      <!-- 前置图标 -->
      <div class="input-prepend">
        <SvgIcon
          :name="state.fontIconPrefix === '' ? prepend : state.fontIconPrefix"
          class="prepend-icon"
          :aria-hidden="true"
        />
      </div>

      <!-- 输入框 -->
      <input
        v-model="inputDisplayValue"
        :placeholder="state.fontIconPlaceholder"
        :disabled="disabled"
        ref="inputWidthRef"
        class="custom-input"
        role="textbox"
        :aria-label="placeholder"
        :aria-describedby="state.error ? 'icon-selector-error' : undefined"
        @focus="onIconFocus"
        @blur="onIconBlur"
        @input="onInputChange"
        @keydown="onKeyDown"
      />

      <!-- 清空按钮 -->
      <div
        v-if="clearable && inputDisplayValue && !disabled"
        class="input-clear"
        @click="onClearFontIcon"
        role="button"
        tabindex="0"
        aria-label="清空内容"
        @keydown="onClearKeyDown"
      >
        ✕
      </div>
    </div>
    <!-- 自定义下拉框 -->
    <div
      v-if="state.isSearching"
      class="icon-dropdown"
      :style="{ width: state.fontIconWidth + 'px' }"
      role="listbox"
      :aria-label="`图标选择器，当前选中：${state.fontIconPrefix || '无'}`"
    >
      <!-- 标签页导航 -->
      <div class="icon-tabs">
        <div
          class="tab-item"
          :class="{ 'tab-active': state.fontIconTabActive === 'ali' }"
          @click="onTabClick('ali')"
          @mousedown="onAliMouseDown"
          @keydown="onTabKeyDown('ali', $event)"
          role="tab"
          :aria-selected="state.fontIconTabActive === 'ali'"
          tabindex="0"
        >
          阿里图标
        </div>
        <div
          class="tab-item"
          :class="{ 'tab-active': state.fontIconTabActive === 'ele' }"
          @click="onTabClick('ele')"
          @mousedown="onElementPlusMouseDown"
          @keydown="onTabKeyDown('ele', $event)"
          role="tab"
          :aria-selected="state.fontIconTabActive === 'ele'"
          tabindex="0"
        >
          Element Plus 图标
        </div>
      </div>

      <!-- 图标列表内容 -->
      <div class="icon-content">
        <IconList
          :list="fontIconSheetsFilterList"
          :empty="emptyDescription"
          :prefix="state.fontIconPrefix"
          :loading="state.loading"
          @get-icon="onColClick"
        />
      </div>

      <!-- 错误提示 -->
      <div
        v-if="state.error"
        id="icon-selector-error"
        class="icon-selector-error"
        role="alert"
      >
        {{ state.error }}
      </div>

      <!-- 加载状态 -->
      <div
        v-if="state.loading"
        class="icon-selector-loading"
        role="status"
        aria-live="polite"
      >
        正在加载图标...
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  reactive,
  onMounted,
  nextTick,
  computed,
  watch,
  onErrorCaptured,
  onUnmounted,
  getCurrentInstance,
} from 'vue';
import {
  getAlicdnIconfont,
  getElementPlusIconfont,
  elSvg,
  alSvg,
} from '../utils/init';

// 引入组件
import IconList from './list.vue';

// 定义父组件传过来的值
const props = withDefaults(
  defineProps<{
    // 输入框前置内容
    prepend?: string;
    // 输入框占位文本
    placeholder?: string;
    // 输入框大小
    size?: 'small' | 'default' | 'large';
    // 是否禁用
    disabled?: boolean;
    // 是否可清空
    clearable?: boolean;
    // 自定义空状态描述文字
    emptyDescription?: string;
    // 双向绑定值
    modelValue?: string;
    // 是否显示搜索框
    showSearch?: boolean;
    // 是否显示标签页
    showTabs?: boolean;
    // 最大高度
    maxHeight?: number;
    // 搜索防抖延迟
    searchDebounce?: number;
  }>(),
  {
    prepend: 'ele-Pointer',
    placeholder: '请输入内容搜索图标或者选择图标',
    size: 'default',
    disabled: false,
    clearable: true,
    emptyDescription: '无相关图标',
    modelValue: '',
    showSearch: true,
    showTabs: true,
    maxHeight: 230,
    searchDebounce: 300,
  }
);

// 定义子组件向父组件传值/事件
const emit = defineEmits(['update:modelValue', 'get', 'clear']);

// 定义变量内容
const inputWidthRef = ref();
const state = reactive({
  fontIconPrefix: '',
  fontIconWidth: 0,
  fontIconSearch: '',
  fontIconPlaceholder: '',
  fontIconTabActive: 'ali',
  fontIconList: {
    ali: [] as string[],
    ele: [] as string[],
  },
  isSearching: false, // 是否正在搜索
  loading: false, // 加载状态
  error: '', // 错误信息
  retryCount: 0, // 重试次数
  // 添加加载状态跟踪
  loadedTabs: new Set<string>(), // 已加载的标签页
  loadingTabs: new Set<string>(), // 正在加载的标签页
});

// 错误处理
onErrorCaptured((error: Error) => {
  console.error('IconSelector Error:', error);
  state.error = error.message;
  return false;
});

// 防抖函数
const debounce = (func: Function, delay: number) => {
  let timeoutId: NodeJS.Timeout;
  return (...args: any[]) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(null, args), delay);
  };
};

// 清理函数
const cleanup = () => {
  window.removeEventListener('resize', getInputWidth);
  // 清理状态
  state.loadedTabs.clear();
  state.loadingTabs.clear();
  searchCache.clear();
};

// 输入框显示值的计算属性
const inputDisplayValue = computed({
  get: () => {
    // 如果正在搜索，显示搜索内容；否则显示选中的图标
    if (state.isSearching) {
      return state.fontIconSearch;
    }
    // 优先显示当前选中的图标
    return state.fontIconPrefix || '';
  },
  set: (value: string) => {
    state.fontIconSearch = value;
    state.isSearching = value.trim() !== '';
  },
});

// 防抖搜索函数
const debouncedSearch = debounce((value: string) => {
  state.fontIconSearch = value;
  state.isSearching = value.trim() !== '';
}, props.searchDebounce);

// 处理搜索输入
const onSearchInput = (value: string) => {
  debouncedSearch(value);
};

// 处理 input 事件
const onInputChange = (event: Event) => {
  const target = event.target as HTMLInputElement;
  onSearchInput(target.value);
};

// 处理 input 获取焦点时
const onIconFocus = () => {
  // 开始搜索模式
  state.isSearching = true;
  state.fontIconSearch = '';
};

// 处理 input 失去焦点时
const onIconBlur = () => {
  // 退出搜索模式
  state.isSearching = false;
  state.fontIconSearch = '';
};

// 键盘导航处理
const onKeyDown = (event: KeyboardEvent) => {
  switch (event.key) {
    case 'Escape':
      // ESC 键关闭选择器
      state.isSearching = false;
      state.fontIconSearch = '';
      inputWidthRef.value?.blur();
      break;
    case 'Enter':
      // Enter 键确认选择
      if (state.fontIconPrefix) {
        onColClick(state.fontIconPrefix);
      }
      break;
    case 'ArrowDown':
      // 下箭头键打开选择器
      event.preventDefault();
      if (!state.isSearching) {
        state.isSearching = true;
        state.fontIconSearch = '';
      }
      break;
  }
};
// 搜索缓存
const searchCache = new Map<string, string[]>();

// 图标搜索及图标数据显示
const fontIconSheetsFilterList = computed(() => {
  const list = fontIconTabNameList();
  if (!state.fontIconSearch) return list;

  const search = state.fontIconSearch.trim().toLowerCase();
  const cacheKey = `${state.fontIconTabActive}-${search}`;

  // 检查缓存
  if (searchCache.has(cacheKey)) {
    return searchCache.get(cacheKey)!;
  }

  // 执行搜索
  const filteredList = list.filter((item: string) => {
    return item.toLowerCase().indexOf(search) !== -1;
  });

  // 缓存结果
  searchCache.set(cacheKey, filteredList);

  // 限制缓存大小
  if (searchCache.size > 100) {
    const firstKey = searchCache.keys().next().value;
    if (firstKey) {
      searchCache.delete(firstKey);
    }
  }

  return filteredList;
});
// 根据 tab name 类型设置图标
const fontIconTabNameList = () => {
  let iconList: any = [];
  if (state.fontIconTabActive === 'ali') iconList = state.fontIconList.ali;
  else if (state.fontIconTabActive === 'ele') iconList = state.fontIconList.ele;
  return iconList;
};
// 处理 icon 双向绑定数值回显
const initModeValueEcho = () => {
  if (props.modelValue === '') {
    state.fontIconPlaceholder = props.placeholder;
    state.fontIconPrefix = '';
    state.isSearching = false;
  } else {
    state.fontIconPlaceholder = props.modelValue;
    state.fontIconPrefix = props.modelValue;
    state.isSearching = false;
  }
};
// 处理 icon 类型，用于回显时，tab 高亮与初始化数据
const initFontIconName = () => {
  let name = 'ali';
  if (props.modelValue && props.modelValue.indexOf('ali-') > -1) name = 'ali';
  else if (props.modelValue && props.modelValue.indexOf('ele-') > -1)
    name = 'ele';
  // 初始化 tab 高亮回显
  state.fontIconTabActive = name;
  return name;
};
// 初始化数据
const initFontIconData = async (name: string, forceReload = false) => {
  // 检查是否已经加载过或正在加载中
  if (!forceReload) {
    if (state.loadedTabs.has(name)) return;
    if (state.loadingTabs.has(name)) return;
  }

  // 标记为正在加载
  state.loadingTabs.add(name);
  state.loading = true;
  state.error = '';

  try {
    if (name === 'ali') {
      // 阿里字体图标使用 `iconfont xxx`
      const res = await getAlicdnIconfont();
      state.fontIconList.ali = res as string[];
      state.retryCount = 0;
    } else if (name === 'ele') {
      // element plus 图标
      const res = await getElementPlusIconfont();
      state.fontIconList.ele = res as string[];
      state.retryCount = 0;
    }

    // 标记为已加载
    state.loadedTabs.add(name);
  } catch (error) {
    console.error(`Failed to load ${name} icons:`, error);
    state.error = `加载${name === 'ali' ? '阿里' : 'Element Plus 图标'}失败`;
    state.retryCount++;

    // 自动重试机制
    if (state.retryCount < 3) {
      setTimeout(() => {
        initFontIconData(name, true); // 强制重新加载
      }, 1000 * state.retryCount);
    }
  } finally {
    // 移除加载中状态
    state.loadingTabs.delete(name);
    state.loading = false;
  }

  // 只有在初始化时才设置 placeholder 和回显
  if (forceReload || (!state.fontIconPrefix && !state.isSearching)) {
    state.fontIconPlaceholder = props.placeholder || '';
    initModeValueEcho();
  }
};
// 阿里图标标签页 mousedown 处理
const onAliMouseDown = (event: MouseEvent) => {
  event.preventDefault();
  event.stopPropagation();
  onTabClick('ali');
};

// Element Plus 图标标签页 mousedown 处理
const onElementPlusMouseDown = (event: MouseEvent) => {
  event.preventDefault();
  event.stopPropagation();
  onTabClick('ele');
};

// 标签页点击切换
const onTabClick = (tabName: string) => {
  // 更新当前激活的标签页
  state.fontIconTabActive = tabName;

  // 确保保持搜索状态
  state.isSearching = true;

  // 如果已经加载过，直接切换，不重新加载
  if (state.loadedTabs.has(tabName)) {
    inputWidthRef.value?.focus();
    return;
  }

  // 只有在需要时才加载数据
  initFontIconData(tabName);
  inputWidthRef.value?.focus();
};

// 标签页键盘导航
const onTabKeyDown = (tabName: string, event: KeyboardEvent) => {
  switch (event.key) {
    case 'Enter':
    case ' ':
      // Enter 或空格键切换标签页
      event.preventDefault();
      onTabClick(tabName);
      break;
    case 'ArrowLeft':
    case 'ArrowRight':
      // 左右箭头键切换标签页
      event.preventDefault();
      const tabs = ['ali', 'ele'];
      const currentIndex = tabs.indexOf(tabName);
      const nextIndex =
        event.key === 'ArrowLeft'
          ? (currentIndex - 1 + tabs.length) % tabs.length
          : (currentIndex + 1) % tabs.length;
      const nextTab = tabs[nextIndex];
      if (nextTab) {
        onTabClick(nextTab);
      }
      break;
    case 'Escape':
      // ESC 键关闭下拉框
      event.preventDefault();
      state.isSearching = false;
      state.fontIconSearch = '';
      inputWidthRef.value?.blur();
      break;
  }
};

// 图标点击切换（保留兼容性）
// const onIconClick = (pane: TabsPaneContext) => {
//   const tabName = pane.paneName as string;
//   onTabClick(tabName);
// };
// 获取当前点击的 icon 图标
const onColClick = (v: string) => {
  // 设置选中的图标
  state.fontIconPlaceholder = v;
  state.fontIconPrefix = v;

  // 清空搜索状态
  state.fontIconSearch = '';
  state.isSearching = false;

  // 触发事件
  emit('get', state.fontIconPrefix);
  emit('update:modelValue', state.fontIconPrefix);

  // 点击图标后，让输入框失去焦点
  inputWidthRef.value.blur();
};
// 清空当前点击的 icon 图标
const onClearFontIcon = () => {
  state.fontIconPrefix = '';
  state.fontIconPlaceholder = props.placeholder;
  state.fontIconSearch = '';
  state.isSearching = false; // 退出搜索模式
  emit('clear', state.fontIconPrefix);
  emit('update:modelValue', state.fontIconPrefix);
};

// 清空按钮键盘事件
const onClearKeyDown = (event: KeyboardEvent) => {
  switch (event.key) {
    case 'Enter':
    case ' ':
      // Enter 或空格键清空
      event.preventDefault();
      onClearFontIcon();
      break;
    case 'Escape':
      // ESC 键关闭下拉框
      event.preventDefault();
      state.isSearching = false;
      state.fontIconSearch = '';
      inputWidthRef.value?.blur();
      break;
  }
};
// 获取 input 的宽度
const getInputWidth = () => {
  nextTick(() => {
    if (inputWidthRef.value) {
      state.fontIconWidth = inputWidthRef.value.offsetWidth;
    }
  });
};
// 监听页面宽度改变
const initResize = () => {
  window.addEventListener('resize', () => {
    getInputWidth();
  });
};
// 页面加载时
onMounted(() => {
  // 自动注入样式（如果还没有注入）
  if (
    typeof window !== 'undefined' &&
    !document.querySelector('style[data-menu-icon]')
  ) {
    const style = document.createElement('style');
    style.setAttribute('data-menu-icon', 'true');
    style.textContent = `
      .icon-selector-warp-row{height:230px;overflow:hidden;border-radius:6px;background-color:#fff;box-shadow:0 2px 8px rgba(0,0,0,0.1)}@media (max-width: 768px){.icon-selector-warp-row{height:160px}}.icon-selector{width:100%;height:100%;position:relative}.icon-selector .custom-input-wrapper{position:relative;display:flex;align-items:center;border:1px solid #dcdfe6;border-radius:4px;background-color:#fff;transition:all .3s ease;overflow:hidden}.icon-selector .custom-input-wrapper:hover{border-color:#c0c4cc}.icon-selector .custom-input-wrapper:focus-within{border-color:#409eff;box-shadow:0 0 0 2px rgba(64,158,255,0.2)}.icon-selector .custom-input-wrapper.input-disabled{background-color:#f5f7fa;border-color:#e4e7ed;cursor:not-allowed}.icon-selector .custom-input-wrapper.input-disabled .custom-input{background-color:transparent;cursor:not-allowed;color:#c0c4cc}.icon-selector .custom-input-wrapper.input-disabled .prepend-icon{color:#c0c4cc}.icon-selector .custom-input-wrapper.input-small{height:28px;font-size:12px}.icon-selector .custom-input-wrapper.input-small .input-prepend{padding:0 8px}.icon-selector .custom-input-wrapper.input-small .custom-input{padding:0 8px;font-size:12px}.icon-selector .custom-input-wrapper.input-small .input-clear{width:20px;height:20px;font-size:12px}.icon-selector .custom-input-wrapper.input-default{height:32px;font-size:14px}.icon-selector .custom-input-wrapper.input-default .input-prepend{padding:0 12px}.icon-selector .custom-input-wrapper.input-default .custom-input{padding:0 12px;font-size:14px}.icon-selector .custom-input-wrapper.input-default .input-clear{width:24px;height:24px;font-size:14px}.icon-selector .custom-input-wrapper.input-large{height:36px;font-size:16px}.icon-selector .custom-input-wrapper.input-large .input-prepend{padding:0 16px}.icon-selector .custom-input-wrapper.input-large .custom-input{padding:0 16px;font-size:16px}.icon-selector .custom-input-wrapper.input-large .input-clear{width:28px;height:28px;font-size:16px}.icon-selector .input-prepend{display:flex;align-items:center;justify-content:center;background-color:#f5f7fa;border-right:1px solid #dcdfe6;color:#909399;height:100%}.icon-selector .input-prepend .prepend-icon{font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center}.icon-selector .custom-input{flex:1;border:none;outline:none;background:transparent;color:#606266;font-family:inherit}.icon-selector .custom-input::placeholder{color:#c0c4cc}.icon-selector .custom-input:disabled{cursor:not-allowed;color:#c0c4cc}.icon-selector .input-clear{display:flex;align-items:center;justify-content:center;cursor:pointer;color:#c0c4cc;transition:color .3s ease;border-radius:50%;margin-right:8px}.icon-selector .input-clear:hover{color:#909399;background-color:#f5f7fa}.icon-selector .input-clear:focus{outline:2px solid #409eff;outline-offset:2px}.icon-selector .icon-dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;background:#fff;border:1px solid #e4e7ed;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.15);margin-top:4px;overflow:hidden;animation:dropdownFadeIn .2s ease-out}@keyframes dropdownFadeIn{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.icon-selector .icon-tabs{display:flex;border-bottom:1px solid #e4e7ed;background:#fafafa}.icon-selector .icon-tabs .tab-item{flex:1;padding:12px 16px;text-align:center;cursor:pointer;font-size:14px;color:#606266;border-bottom:2px solid transparent;transition:all .3s ease;user-select:none}.icon-selector .icon-tabs .tab-item:hover{color:#409eff;background-color:#f0f9ff}.icon-selector .icon-tabs .tab-item:focus{outline:2px solid #409eff;outline-offset:-2px}.icon-selector .icon-tabs .tab-item.tab-active{color:#409eff;border-bottom-color:#409eff;background-color:#fff;font-weight:500}.icon-selector .icon-content{position:relative}.icon-selector .icon-selector-warp-row{height:230px!important;overflow:hidden;border-radius:6px;background-color:#fff;box-shadow:0 2px 8px rgba(0,0,0,0.1)}.icon-selector .icon-selector-warp-row .icon-scroll-container{height:100%;overflow-y:auto;overflow-x:hidden;padding:10px}.icon-selector .icon-selector-warp-row .icon-scroll-container::-webkit-scrollbar{width:6px}.icon-selector .icon-selector-warp-row .icon-scroll-container::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.icon-selector .icon-selector-warp-row .icon-scroll-container::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:3px}.icon-selector .icon-selector-warp-row .icon-scroll-container::-webkit-scrollbar-thumb:hover{background:#a8a8a8}.icon-selector .icon-selector-warp-row .icon-scroll-container{scrollbar-width:thin;scrollbar-color:#c1c1c1 #f1f1f1}.icon-selector .icon-selector-warp-row .icon-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px;padding:0}.icon-selector .icon-selector-warp-row .icon-item{display:flex;justify-content:center;align-items:center;border:1px solid #e4e7ed;border-radius:5px;height:40px;cursor:pointer;pointer-events:auto;user-select:none;transition:all .3s ease;background-color:#fff}.icon-selector .icon-selector-warp-row .icon-item i{font-size:20px;color:#606266;pointer-events:none;transition:color .3s ease}.icon-selector .icon-selector-warp-row .icon-item:hover{cursor:pointer;background-color:#f0f9ff;border:1px solid #b3d8ff;transform:translateY(-1px);box-shadow:0 2px 4px rgba(0,0,0,0.1)}.icon-selector .icon-selector-warp-row .icon-item:hover i{color:#409eff}.icon-selector .icon-selector-warp-row .icon-item:focus{outline:2px solid #409eff;outline-offset:2px}.icon-selector .icon-selector-warp-row .icon-item-active{background-color:#f0f9ff;border:1px solid #b3d8ff}.icon-selector .icon-selector-warp-row .icon-item-active i{color:#409eff}.icon-selector .icon-selector-warp-row .icon-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:#909399;padding:20px}.icon-selector .icon-selector-warp-row .icon-empty .empty-icon{font-size:48px;margin-bottom:12px;opacity:.6}.icon-selector .icon-selector-warp-row .icon-empty .empty-text{font-size:14px;text-align:center}@media (max-width: 768px){.icon-selector .custom-input-wrapper.input-small{height:26px;font-size:11px}.icon-selector .custom-input-wrapper.input-small .input-prepend{padding:0 6px}.icon-selector .custom-input-wrapper.input-small .custom-input{padding:0 6px;font-size:11px}.icon-selector .custom-input-wrapper.input-small .input-clear{width:18px;height:18px;font-size:11px}.icon-selector .custom-input-wrapper.input-default{height:30px;font-size:13px}.icon-selector .custom-input-wrapper.input-default .input-prepend{padding:0 10px}.icon-selector .custom-input-wrapper.input-default .custom-input{padding:0 10px;font-size:13px}.icon-selector .custom-input-wrapper.input-default .input-clear{width:22px;height:22px;font-size:13px}.icon-selector .custom-input-wrapper.input-large{height:34px;font-size:15px}.icon-selector .custom-input-wrapper.input-large .input-prepend{padding:0 14px}.icon-selector .custom-input-wrapper.input-large .custom-input{padding:0 14px;font-size:15px}.icon-selector .custom-input-wrapper.input-large .input-clear{width:26px;height:26px;font-size:15px}.icon-selector .icon-dropdown .icon-tabs .tab-item{padding:10px 12px;font-size:13px}.icon-selector .icon-selector-warp-row{height:160px!important}.icon-selector .icon-selector-warp-row .icon-scroll-container{padding:8px}.icon-selector .icon-selector-warp-row .icon-grid{grid-template-columns:repeat(4,1fr);gap:6px}.icon-selector .icon-selector-warp-row .icon-item{height:36px}.icon-selector .icon-selector-warp-row .icon-item i{font-size:16px}.icon-selector .icon-selector-warp-row .icon-empty .empty-icon{font-size:36px}.icon-selector .icon-selector-warp-row .icon-empty .empty-text{font-size:12px}}.icon-selector-error{color:#f56c6c;font-size:12px;padding:8px 16px;background-color:#fef0f0;border:1px solid #fbc4c4;border-radius:4px;margin-top:8px}.icon-selector-loading{color:#409eff;font-size:12px;padding:8px 16px;text-align:center;background-color:#f0f9ff;border:1px solid #b3d8ff;border-radius:4px;margin-top:8px}.icon-selector-warp-item:focus{outline:2px solid #409eff;outline-offset:2px}.icon-selector-warp-item:focus-visible{outline:2px solid #409eff;outline-offset:2px}@media (prefers-color-scheme: dark){.icon-selector .icon-dropdown{background-color:#1d1e1f;border:1px solid #4c4d4f}}
    `;
    document.head.appendChild(style);
  }

  // 备用图标注册机制
  const instance = getCurrentInstance();
  if (instance?.appContext?.app) {
    const app = instance.appContext.app;
    const registeredComponents = app._context?.components || {};
    const hasElementIcons = Object.keys(registeredComponents).some((key) =>
      key.startsWith('ele-')
    );
    const hasAntIcons = Object.keys(registeredComponents).some((key) =>
      key.startsWith('ali-')
    );

    if (!hasElementIcons || !hasAntIcons) {
      console.warn('[MenuIcon] 图标未正确注册，正在尝试重新注册...');
      if (!hasElementIcons) {
        elSvg(app);
      }
      if (!hasAntIcons) {
        alSvg(app);
      }
    }
  }

  initFontIconData(initFontIconName());
  initResize();
  getInputWidth();
});

// 组件卸载时清理
onUnmounted(() => {
  cleanup();
});

// 监听双向绑定 modelValue 的变化
watch(
  () => props.modelValue,
  () => {
    initModeValueEcho();
    initFontIconName();
  }
);
</script>
